﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.IO;
using System.Windows.Browser;

namespace CurveMenuPanel
{
    public class CurveMenuItem : Control
    {

       public bool IsInit = false;
       public bool IsImgNull = true;


        #region CaptionEnabled (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public bool CaptionEnabled
        {
            get { return (bool)GetValue(CaptionEnabledProperty); }
            set { SetValue(CaptionEnabledProperty, value); }
        }
        public static readonly DependencyProperty CaptionEnabledProperty =
            DependencyProperty.Register("CaptionEnabled", typeof(bool), typeof(CurveMenuItem),
            new PropertyMetadata(true, new PropertyChangedCallback(OnCaptionEnabledChanged)));

        private static void OnCaptionEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnCaptionEnabledChanged(e);
        }

        protected virtual void OnCaptionEnabledChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                xCaption.Visibility = ((bool)e.NewValue) ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        #endregion

        #region CaptionDistance (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double CaptionDistance
        {
            get { return (double)GetValue(CaptionDistanceProperty); }
            set { SetValue(CaptionDistanceProperty, value); }
        }
        public static readonly DependencyProperty CaptionDistanceProperty =
            DependencyProperty.Register("CaptionDistance", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnCaptionDistanceChanged)));

        private static void OnCaptionDistanceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnCaptionDistanceChanged(e);
        }

        protected virtual void OnCaptionDistanceChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                CaptiontranslateTransform.Y = (double)e.NewValue;
            }
        }

        #endregion

        #region alpha (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double alpha
        {
            get { return (double)GetValue(alphaProperty); }
            set { SetValue(alphaProperty, value); }
        }
        public static readonly DependencyProperty alphaProperty =
            DependencyProperty.Register("alpha", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(1.0, new PropertyChangedCallback(OnalphaChanged)));

        private static void OnalphaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnalphaChanged(e);
        }

        protected virtual void OnalphaChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                this.Opacity = (double)e.NewValue;
            }
        }

        #endregion

        #region visible (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public bool visible
        {
            get { return (bool)GetValue(visibleProperty); }
            set { SetValue(visibleProperty, value); }
        }
        public static readonly DependencyProperty visibleProperty =
            DependencyProperty.Register("visible", typeof(bool), typeof(CurveMenuItem),
            new PropertyMetadata(true, new PropertyChangedCallback(OnvisibleChanged)));

        private static void OnvisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnvisibleChanged(e);
        }

        protected virtual void OnvisibleChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                this.Visibility = ((bool)e.NewValue) ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        #endregion

        #region Scale (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double Scale
        {
            get { return (double)GetValue(ScaleProperty); }
            set { SetValue(ScaleProperty, value); }
        }
        public static readonly DependencyProperty ScaleProperty =
            DependencyProperty.Register("Scale", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(1.0, new PropertyChangedCallback(OnScaleChanged)));

        private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnScaleChanged(e);
        }

        protected virtual void OnScaleChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                scaleTransform.ScaleX = (double)e.NewValue;
                scaleTransform.ScaleY = (double)e.NewValue;
            }
        }

        #endregion


        #region x (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double x
        {
            get { return (double)GetValue(xProperty); }
            set { SetValue(xProperty, value); }
        }
        public static readonly DependencyProperty xProperty =
            DependencyProperty.Register("x", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnxChanged)));

        private static void OnxChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnxChanged(e);
        }

        protected virtual void OnxChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                translateTransform.X = (double)e.NewValue;
            }
        }

        #endregion


        #region y (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double y
        {
            get { return (double)GetValue(yProperty); }
            set { SetValue(yProperty, value); }
        }
        public static readonly DependencyProperty yProperty =
            DependencyProperty.Register("y", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnyChanged)));

        private static void OnyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnyChanged(e);
        }

        protected virtual void OnyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                translateTransform.Y = (double)e.NewValue;
            }
        }

        #endregion


        #region rotation (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double rotation
        {
            get { return (double)GetValue(rotationProperty); }
            set { SetValue(rotationProperty, value); }
        }
        public static readonly DependencyProperty rotationProperty =
            DependencyProperty.Register("rotation", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnrotationChanged)));

        private static void OnrotationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnrotationChanged(e);
        }

        protected virtual void OnrotationChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                rotateTransform.Angle = (double)e.NewValue;
            }
        }

        #endregion


        #region ItemWitch (DependencyProperty)

        /// <summary>
        /// ItemWitch
        /// </summary>
        public double ItemWitch
        {
            get { return (double)GetValue(ItemWitchProperty); }
            set { SetValue(ItemWitchProperty, value); }
        }
        public static readonly DependencyProperty ItemWitchProperty =
            DependencyProperty.Register("ItemWitch", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(75.0, new PropertyChangedCallback(OnItemWitchChanged)));

        private static void OnItemWitchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnItemWitchChanged(e);
        }

        protected virtual void OnItemWitchChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                this.LayoutRoot.Width = (double)e.NewValue;
            }
        }

        #endregion




        #region RotationY (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public double RotationY
        {
            get { return (double)GetValue(RotationYProperty); }
            set { SetValue(RotationYProperty, value); }
        }
        public static readonly DependencyProperty RotationYProperty =
            DependencyProperty.Register("RotationY", typeof(double), typeof(CurveMenuItem),
            new PropertyMetadata(0.0, new PropertyChangedCallback(OnRotationYChanged)));

        private static void OnRotationYChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnRotationYChanged(e);
        }

        protected virtual void OnRotationYChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                this.planeProjection.RotationY = (double)e.NewValue;
            }
        }

        #endregion




        #region MyItemData (DependencyProperty)

        /// <summary>
        /// A description of the property.
        /// </summary>
        public ItemData MyItemData
        {
            get { return (ItemData)GetValue(MyItemDataProperty); }
            set { SetValue(MyItemDataProperty, value); }
        }
        public static readonly DependencyProperty MyItemDataProperty =
            DependencyProperty.Register("MyItemData", typeof(ItemData), typeof(CurveMenuItem),
            new PropertyMetadata(null, new PropertyChangedCallback(OnMyItemDataChanged)));

        private static void OnMyItemDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CurveMenuItem)d).OnMyItemDataChanged(e);
        }

        protected virtual void OnMyItemDataChanged(DependencyPropertyChangedEventArgs e)
        {
            if (IsInit)
            {
                LoadImage(new Uri(HtmlPage.Document.DocumentUri, ((ItemData)e.NewValue).imageUri));
                xCaption.Text = ((ItemData)e.NewValue).title;
            }
        }

        #endregion

        public void LoadImage(Uri uri)
        {
            WebClient client = new WebClient();
            client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
            client.OpenReadAsync(uri);
        }

        void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                BitmapImage bi = new BitmapImage();
                bi.SetSource(e.Result as Stream);
                xImg.Source = bi;
                IsImgNull = false;
            }
        }


        TranslateTransform translateTransform;
        RotateTransform rotateTransform;
        ScaleTransform scaleTransform;
        PlaneProjection planeProjection;

        TranslateTransform CaptiontranslateTransform;



        public int pos = 0;


        public Image xImg;
        public TextBlock xCaption;
        StackPanel LayoutRoot;
        public CurveMenuItem(int p)
            : base()
        {

            DefaultStyleKey = typeof(CurveMenuItem);
            pos = p;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            LayoutRoot = this.GetTemplateChild<StackPanel>("LayoutRoot");
            xImg = this.GetTemplateChild<Image>("xImg");
            xCaption = this.GetTemplateChild<TextBlock>("xCaption");


            var transformGroup = this.RenderTransform as TransformGroup;
            if (transformGroup == null)
            {
                transformGroup = new TransformGroup();
                this.RenderTransform = transformGroup;

                translateTransform = new TranslateTransform();
                transformGroup.Children.Add(translateTransform);
            }

            //矫正
            var Correction = new TranslateTransform();
            Correction.X = -this.ActualWidth / 2;
            Correction.Y = -this.ActualHeight / 2;
            transformGroup.Children.Add(Correction);





            var ltransformGroup = this.LayoutRoot.RenderTransform as TransformGroup;
            if (ltransformGroup == null)
            {

                ltransformGroup = new TransformGroup();
                this.LayoutRoot.RenderTransform = ltransformGroup;



                rotateTransform = new RotateTransform();
                scaleTransform = new ScaleTransform();
                ltransformGroup.Children.Add(rotateTransform);
                ltransformGroup.Children.Add(scaleTransform);

            }

            this.LayoutRoot.RenderTransformOrigin = new Point(0.5, 0.5);


            CaptiontranslateTransform = this.xCaption.RenderTransform as TranslateTransform;
            if (CaptiontranslateTransform == null)
            {
                CaptiontranslateTransform = new TranslateTransform();
                this.xCaption.RenderTransform = CaptiontranslateTransform;
            }


            planeProjection = this.LayoutRoot.Projection as PlaneProjection;
            if (planeProjection == null)
            {
                planeProjection = new PlaneProjection();
                this.LayoutRoot.Projection = planeProjection;
            }

            IsInit = true;
        }

        public void BuildUI()
        {
            LoadImage(new Uri(HtmlPage.Document.DocumentUri, MyItemData.imageUri));
            xCaption.Text = MyItemData.title;

        }

        private T GetTemplateChild<T>(string childName) where T : DependencyObject
        {
            T childControl = this.GetTemplateChild(childName) as T;
            if (childControl == null)
            {
                throw new Exception(string.Format("Couldn't find {0}", childName));
            }
            return childControl;
        }
    }
}
